#if !defined(AFX_SIMPLEMODULUS_H__5EC20CDC_CA87_4F9D_927B_24C8DD11ECB7__INCLUDED_)
#define AFX_SIMPLEMODULUS_H__5EC20CDC_CA87_4F9D_927B_24C8DD11ECB7__INCLUDED_

#pragma once

/*
# define SIZE_ENCRYPTION_BLOCK	( 32)
# define SIZE_ENCRYPTION_KEY	( 16)
# define SIZE_ENCRYPTED_BLOCK	( 38)
*/

# define SIZE_ENCRYPTION_BLOCK	( 16)
# define SIZE_ENCRYPTION_KEY	( 8)	// SIZE_ENCRYPTION_BLOCK Half
# define SIZE_ENCRYPTED_BLOCK	( 20)

/*
# define SIZE_ENCRYPTION_BLOCK	( 8)
# define SIZE_ENCRYPTION_KEY	( 4)	// SIZE_ENCRYPTION_BLOCK Half
# define SIZE_ENCRYPTED_BLOCK	( 11)
*/

class CSimpleModulus
{
public:
	CSimpleModulus();
	virtual ~CSimpleModulus();

	void Init(void);

protected:
	DWORD m_dwModulus[SIZE_ENCRYPTION_KEY];
	DWORD m_dwEncryptionKey[SIZE_ENCRYPTION_KEY];
	DWORD m_dwDecryptionKey[SIZE_ENCRYPTION_KEY];
	DWORD m_dwXORKey[SIZE_ENCRYPTION_KEY];

	static DWORD s_dwSaveLoadXOR[SIZE_ENCRYPTION_KEY];

	//////////////////////////////////////////////////////////////////////////
	// The encryption / decryption ->

	// Encryption
public:
	int Encrypt(void * lpTarget, void * lpSource, int iSize);	// All large size, lpTarget is NULL, the return requirement
	int Decrypt(void * lpTarget, void * lpSource, int iSize);	// All large size, lpTarget is NULL, the return requirement

protected:
	void EncryptBlock(void * lpTarget, void * lpSource, int nSize);	// The 38 byte to 32 byte
	int DecryptBlock(void * lpTarget, void * lpSource);	// The 32 byte to 38 byte, Size and returns as
	int AddBits(void * lpBuffer, int nNumBufferBits, void * lpBits, int nInitialBit, int nNumBits);
	void Shift(void * lpBuffer, int nByte, int nShift);
	int GetByteOfBit(int nBit);

	// <- The encryption / decryption
	//////////////////////////////////////////////////////////////////////////

	// Save / Read
public:
	BOOL SaveAllKey(char * lpszFileName);
	BOOL LoadAllKey(char * lpszFileName);
	BOOL SaveEncryptionKey(char * lpszFileName);
	BOOL LoadEncryptionKey(char * lpszFileName);
	BOOL SaveDecryptionKey(char * lpszFileName);
	BOOL LoadDecryptionKey(char * lpszFileName);
protected:
	BOOL SaveKey(char * lpszFileName, unsigned short sID, BOOL bMod, BOOL bEnc, BOOL bDec, BOOL bXOR);
	BOOL LoadKey(char * lpszFileName, unsigned short sID, BOOL bMod, BOOL bEnc, BOOL bDec, BOOL bXOR);
};

#pragma pack ( 1)
typedef struct
{
	unsigned short m_sID;
	unsigned int m_iSize;
} ChunkHeader;
#pragma pack ()

# define CHUNKID_ALLKEY		( 0x1111)
# define CHUNKID_ONEKEY		( 0x1112)

#endif